Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

16장. EC2 접속과 권한 — 키 페어 · Session Manager · IAM Role

이 장에서 말하고자 하는 것

EC2를 띄웠다면 다음 질문이 생긴다.

“이 서버에 어떻게 접속해서 들어가지?” “이 서버 안의 코드는 어떻게 AWS API를 호출하지?”

이 둘은 다른 문제다.

  • 사람 → 서버 접속 — SSH · Session Manager
  • 서버 코드 → AWS API — IAM Role (Instance Profile)

이 장은 이 두 가지를 각각 정리한다.


1. 전통 방식 — SSH + 키 페어

키 페어 생성

EC2를 만들 때 키 페어를 선택한다.

공개 키 → AWS가 EC2 안에 자동 설치
비공개 키(.pem) → 사용자가 보관

접속

ssh -i my-key.pem ec2-user@<public-ip>
  • ec2-user (Amazon Linux), ubuntu (Ubuntu) 등 OS별 기본 사용자
  • 22번 포트가 열려 있어야 함

키 페어 운영의 어려움

  • .pem 파일을 누가 가졌는지 추적이 어렵다
  • 키 회전이 번거롭다
  • 22 포트를 인터넷에 노출 → 공격 표면
  • 누가 언제 접속했는지 감사 로그가 약하다

운영 환경에서 SSH 키는 점점 안 쓰는 방향이다


2. 더 나은 방식 — AWS Systems Manager Session Manager

[운영자] → AWS 콘솔 / CLI → IAM 검증 → Session Manager → EC2
  • SSH 키 불필요
  • 22 포트 열 필요 없음 (그래서 인터넷에서도 차단 가능)
  • IAM 권한으로 누가 접속할 수 있는지 통제
  • CloudTrail에 모든 세션 기록 (선택적으로 명령까지 기록)
  • 프라이빗 서브넷의 EC2도 직접 접속 가능 (VPC Endpoint 필요)

운영 환경의 기본은 Session Manager 다


3. Session Manager의 동작

1. EC2에 SSM Agent 설치 (Amazon Linux 2023 · Ubuntu 최근 버전은 기본 설치)
2. EC2에 IAM Role 부여 → AmazonSSMManagedInstanceCore
3. EC2가 시작 시 SSM 서비스에 연결 (아웃바운드 443)
4. 운영자가 콘솔/CLI에서 세션 시작

22 포트도, 키 페어도, 인터넷 노출도 필요 없다.


4. EC2가 AWS API를 호출하려면 — IAM Role + Instance Profile

EC2 안의 코드가 S3를 읽거나 DynamoDB에 쓰려면 권한이 필요하다.

[EC2]
  ↑ 받음
[Instance Profile]
  ↑ 담음
[IAM Role]
  ├─ Trust Policy: ec2.amazonaws.com이 받을 수 있음
  └─ Permission Policy: S3 GetObject 등

EC2 안에서

aws s3 ls

를 그냥 호출하면 자동으로 임시 자격증명이 사용된다.

EC2 안에 액세스 키를 절대 박지 않는다
Instance Profile + Role이 그 자리를 대신한다


5. Instance Metadata Service (IMDS)

EC2 안에서 자기 정보를 조회하는 API.

http://169.254.169.254/latest/meta-data/

여기서

  • 자기 인스턴스 ID
  • 자기 IAM Role의 임시 자격증명
  • 자기 보안 그룹 ID
  • 자기 사용자 데이터

등을 받을 수 있다.

IMDSv1 vs IMDSv2

IMDSv1은 보안 취약점이 있어 SSRF 공격으로 악용될 수 있었다.

신규 인스턴스는 무조건 IMDSv2 only

HttpTokens = required
HttpPutResponseHopLimit = 1

6. Bastion vs Session Manager

옛날 패턴 — 외부 노출된 작은 EC2 (Bastion) 를 거쳐 내부 EC2로 SSH.

운영자 → Bastion (퍼블릭) → 내부 EC2

문제:

  • Bastion 자체가 공격 표면
  • 키 관리 · 패치 운영 부담
  • 감사 로그 약함

Session Manager를 쓰면 Bastion 자체가 불필요해진다
정말 SSH가 필요한 환경에서만 Bastion 운영


7. 우리 서비스에서

이 책의 척추는 ECS Fargate라 사람이 컨테이너에 접속할 일이 거의 없다.

사람 → 운영용 일회성 컨테이너 (ECS Exec)
                            ↑ SSM 동일 메커니즘
  • ECS Exec — 컨테이너 안에 셸 접속하는 ECS 기능
  • 권한 모델은 SSM과 같다 (IAM)

EC2 직접 운영이 필요한 경우 (예: 일부 워커, GPU 노드):

[운영자] → Session Manager → EC2 (프라이빗 서브넷)
                  ↑
            VPC Endpoint (com.amazonaws.region.ssm)

8. 직접 확인해보기 — CLI

Session Manager 접속

aws ssm start-session --target i-1234567890abcdef0

브라우저 없이 터미널에서 바로 셸이 열린다.

EC2 안에서 자기 자격증명 보기 (IMDSv2)

TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

ECS Exec — 컨테이너 셸 접속

aws ecs execute-command \
  --cluster msa \
  --task <task-id> \
  --container app \
  --interactive \
  --command "/bin/sh"

9. 코드로는 이렇게 생겼다 — Terraform

# IAM Role (Session Manager + 애플리케이션 권한)
resource "aws_iam_role" "web" {
  name = "web-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "ssm" {
  role       = aws_iam_role.web.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_instance_profile" "web" {
  name = "web-instance-profile"
  role = aws_iam_role.web.name
}

resource "aws_instance" "web" {
  ami                  = data.aws_ami.web.id
  instance_type        = "t3.small"
  subnet_id            = aws_subnet.private_a.id   # 프라이빗
  iam_instance_profile = aws_iam_instance_profile.web.name

  # IMDSv2 강제
  metadata_options {
    http_tokens                 = "required"
    http_put_response_hop_limit = 1
  }

  # SSH 안 열어도 됨 (Session Manager 사용)
  vpc_security_group_ids = [aws_security_group.web.id]
}

AmazonSSMManagedInstanceCore 한 줄이 Session Manager의 핵심.


10. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. 22번 포트를 0.0.0.0/0 에 연다

“잠깐 디버깅” 으로 연 포트가 영영 열려 있다.

Session Manager로 가서 22를 닫는다

안티패턴 2. .pem 키를 Slack/이메일로 공유

누가 가졌는지 추적 안 됨, 퇴사자 회수 어려움.

안티패턴 3. EC2 안에 AWS 액세스 키를 박는다

가장 흔한 보안 사고. 코드 저장소에 박히기까지 한다.

Instance Profile + Role 외 다른 길은 없다

안티패턴 4. IMDSv1을 그대로 두는 옛 인스턴스

신규는 IMDSv2 only. 옛 인스턴스도 점진 전환.


11. 한 줄로 정리

사람 접속은 Session Manager, 코드의 AWS 호출은 Instance Profile + Role.
22 포트와 키 페어는 점점 자리를 비운다.


12. 이 장의 핵심 정리

  1. 사람 → EC2 접속은 Session Manager가 표준이다.
  2. EC2 안 코드의 AWS 호출은 Instance Profile + IAM Role 로.
  3. EC2 안에 액세스 키 박지 않는다.
  4. IMDSv2 only가 신규 인스턴스의 기본값.
  5. Bastion은 거의 불필요 — Session Manager + 프라이빗 서브넷.
  6. ECS Exec은 같은 메커니즘으로 컨테이너 셸을 연다.